#if !defined(SM__GAME_H)
#define SM__GAME_H

#include "SDL.h"

class Display;
class Player;
class Scene;
class Swag;
class Babe;
class Nerd;
class Npc;
class DummyWall;

#include <vector>
#include <map>
#include <string>
#include <deque>
#include "collide.h"
#include "config.h"
#include "sound.h"
#include "Sprite.h"
#include "Photo.h"

// Game class to encapsulate the whole game
class Game 
{
  private:
    Sint32 mTimeLeftInSec;
    Uint32 mStartTimeInMs;

    Display* mpDisplay;
    Scene*   mpScene;
    Player*  mpPlayer;
    map<string, Sprite *> mSprites;
    map<sm_swag_type, vector<string> > mSpriteIds;
    vector<Swag *> mSwaggage;
    typedef vector<Swag *>::iterator SwagIter;
    vector<Babe *> mBabes;
    typedef vector<Babe *>::iterator BabeIter;
    vector<Nerd *> mNerds;
    typedef vector<Nerd *>::iterator NerdIter;
    DummyWall* theWall;
    
    vector<Photo *> mPhotos;
    typedef vector<Photo *>::iterator PhotoIter;
    Uint32 mLastPhotoTimeInMs;
    bool mbPhotoKeyPressed;

    // WARNING: this container DOES NOT own the TouchableObjects - these objects are 
    // owned by mpPlayer, mSwaggage, mNerds and mNonplayers and should be de-allocated 
    // there after emptying this container...
    vector<TouchableObject*> mRenderables;

    XMLNode* mpConfig;

    NodeArray mAllLevels;
    XMLNode* mpCurLevel;

    CollisionMap mColMap;

    // chrome
    SDL_Surface* mpStatusAreaSurf;
    SDL_Surface* mpBlingMarkerSurf;
    bool mbStatusDirty;

    void Init();
    void InitSprites();
    void InitSounds();
    void InitScene();
    void InitChrome();
    void DrawChrome();
    void DrawBackground();
    void DrawFloor();
    void DrawScreen();

    // renders the status area (called from Update())
    void DrawStatus();

    XMLNode* InitConfig(const char* szConfigFilename);

    void crunchCollisionMap(SDL_Surface *s);
    int getSwagPoints(const sm_swag_type& type);

    bool mbResortRenderables; // dirty flag so the renderable objects array is resorted only on movement
    Sound* sound;

    deque<sm_direction> mKeyPressStack;
    typedef deque<sm_direction>::iterator KeyIter;
    bool mbUpKeyPressed;
    bool mbRightKeyPressed;
    bool mbDownKeyPressed;
    bool mbLeftKeyPressed;
  public:
    Game();
    ~Game();

    bool isGameOver() const { return (mTimeLeftInSec <= 0); }

    // called every game loop 
    void update(Uint8* keystate, Uint32 prevTick, Uint32 thisTick);

    XMLNode* getConfig() { return mpConfig; }

    void dumpColMap();
};

#endif // SM__GAME_H
